package iniconf

import (
	"bufio"
	"errors"
	"os"
	"strings"

	"gitee.com/haodreams/libs/config"
	"gitee.com/haodreams/libs/easy"
)

// Conf 支持md格式的配置
type Conf struct {
	path string
	config.Conf
}

// NewConf .
func NewConf() *Conf {
	c := new(Conf)
	c.SetDriverName("ini")
	return c
}

// Load 加载配置来自文件
func Load(file string) (conf config.Configer, err error) {
	c := new(Conf)
	conf, err = c.Load(file)
	return
}

// Load 读取配置
func (m *Conf) Load(file any) (conf config.Configer, err error) {
	path, ok := file.(string)
	if !ok {
		return nil, errors.New("invalid file path")
	}
	conf = m
	m.path = path
	f, err := os.Open(path)
	if err != nil {
		return
	}
	defer f.Close()
	buf := bufio.NewReader(f)
	desc := easy.NewBufferWithSize(4096)
	var kvs []*config.KV
	orderNo := 0
	for line, err := buf.ReadString('\n'); err == nil || len(line) > 0; line, err = buf.ReadString('\n') {
		orderNo++
		line = strings.TrimSpace(line)
		if line == "" {
			desc.WriteString(line + "  \n")
			continue
		}
		if !easy.IsLetter(line[0]) {
			desc.WriteString(line + "  \n")
			continue
		}
		ss := strings.SplitN(line, "=", 2)
		if len(ss) < 2 {
			desc.WriteString(line + "  \n")
			continue
		}
		for i := range ss {
			ss[i] = strings.TrimSpace(ss[i])
		}
		if len(ss[0]) == 0 {
			desc.WriteString(line + "  \n")
			continue
		}
		kv := new(config.KV)
		kv.Name = ss[0]
		kv.Value = config.DecodeValue(ss[1])
		kv.Desc = desc.String()
		kv.OrderNo = orderNo
		desc.Reset()
		kvs = append(kvs, kv)
	}
	m.SetList(kvs)
	return
}

// Save 保存配置
func (m *Conf) Save(file ...any) (err error) {
	path := m.path
	var ok bool
	if len(file) > 0 {
		if path, ok = file[0].(string); !ok {
			return errors.New("invalid file path")
		}
	}
	m.Lock()
	defer m.Unlock()

	f, err := os.Create(path)
	if err != nil {
		return
	}
	defer f.Close()

	list := m.List()

	for _, conf := range list {
		if conf.Desc != "" {
			f.WriteString(conf.Desc)
			if !strings.HasSuffix(conf.Desc, "\n") {
				f.WriteString("  \n")
			}
		}
		if strings.Contains(conf.Name, "password") && conf.Value != "" { //对含有密码的字符串自动加密
			value := config.EncodeValue(conf.Value) //加密密码
			f.WriteString(conf.Name + "=" + value + "\n")
		} else {
			f.WriteString(conf.Name + "=" + conf.Value + "\n")
		}
	}
	return
}
